package edu.poly.game.player.impl;

import java.util.HashSet;
import java.util.Set;

import edu.poly.game.battleship.BattleShip;
import edu.poly.game.board.GameBoard;
import edu.poly.game.board.impl.GameBoardFactory;
import edu.poly.game.player.MissileFireResult;
import edu.poly.game.player.MissileFireResultType;
import edu.poly.game.player.Player;
import edu.poly.game.player.PlayerType;
import edu.poly.game.stats.GameStats;
import edu.poly.game.util.Coordinate;
import edu.poly.game.util.Dimension;

public class PlayerImpl implements Player {
	
	private boolean automatic;
	private PlayerType playerType;
	private Set<Coordinate> coordinateHistory;
	
	//lose coupling, don't care board's underlying implementation
	private GameBoard myGameBoard;
	
	private GameStats stats;
	
	public PlayerImpl(final PlayerType playerType, final Dimension boardDimension, final int numberOfMissiles) {
		this.playerType = playerType;
		if(this.playerType.equals(PlayerType.COMPUTER)) {
			this.automatic = true;
		} else {
			this.automatic = false;
		}
		
		//using factory method, i don't care how to create a board
		this.myGameBoard = GameBoardFactory.getGameBoard(boardDimension);
		this.stats = new GameStats(numberOfMissiles);
		this.coordinateHistory = new HashSet<Coordinate>();
	}

	@Override
	public PlayerType getPlayerType() {
		return this.playerType;
	}

	@Override
	public MissileFireResult receiveMissileHit(final Coordinate coordinate) {
		if(this.coordinateHistory.contains(coordinate)) {
			return MissileFireResult.getResult(MissileFireResultType.ALREADYHITCOORDINATE, null);
		}
		this.coordinateHistory.add(coordinate);
		return this.myGameBoard.receiveMissileHit(coordinate);
	}

	@Override
	public boolean isAutomatic() {
		return this.automatic;
	}

	@Override
	public boolean addBattleShip(BattleShip battleShip) {
		return this.myGameBoard.addBattleShip(battleShip);
	}

	@Override
	public char[][] getGameBoard() {
		return this.myGameBoard.getGameBoard();
	}

	@Override
	public void processResult(final MissileFireResult result) {
		MissileFireResultType type = result.getResultType();
		switch(type) {
			case HIT: 
					  this.stats.addShipDestroyed(result.getShipType());
					  this.stats.incrementSuccessHit();
					  this.stats.incrementMissileUsed();
					  break;
			case MISSED:
				      this.stats.incrementMissedHit();
				      this.stats.incrementMissileUsed();
					  break;
		}
	}

	@Override
	public GameStats getGameStats() {
		return this.stats;
	}

	@Override
	public boolean hasMoreShips() {
		return this.myGameBoard.hasShipsActive();
	}
}
